home *** CD-ROM | disk | FTP | other *** search
-
- #include "FinderDrag.h" // nothing interesting is in FinderDrag.h
- #include "StringLib.h"
- #include "Spaces.h"
- #include "FinderStuff.h"
- #include "MoreDesktopMgr.h"
-
- // menu constants
- #define kAppleMenuID 1
- #define kAboutMenuItem 1
- #define kFileMenuID 2
- #define kNewMenuItem 1
- #define kOpenMenuItem 2
- #define kCloseMenuItem 3
- #define kQuitMenuItem 5
-
-
-
- // general global variables
-
- Boolean gQuitFlag; // true when the app should exit the main event loop
-
- Boolean gHasColorQuickdrawFlag; // Gestalt info
-
- MenuHandle gAppleMenuHandle, gFileMenuHandle;
-
- unsigned short gWindowCounter;
-
- DragHandlerGlobals gDragHandlerGlobals;
-
-
- /***************************************************
- * Drag support routines
- *
- * These are the installed drag handler routines
- * and supporting functions
- ***************************************************/
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
- // InstallDragHandlers attaches my tracking and receive handlers to
- // one of the application's windows
-
- OSErr InstallDragHandlers(WindowPtr win)
- {
- OSErr err;
-
- // install our tracking and receive handlers for the window
- err = InstallTrackingHandler(MyTrackingHandler, win, NULL);
-
- if (err == noErr) {
- err = InstallReceiveHandler(MyReceiveHandler, win, NULL);
- if (err != noErr)
- (void) RemoveTrackingHandler(MyTrackingHandler, win);
- }
-
- return err;
- }
-
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
- // RemoveDragHandlers removes my tracking and receive handlers from
- // one of the application's windows (prior to the window's disposal,
- // presumably)
-
- void RemoveDragHandlers(WindowPtr win)
- {
- RemoveReceiveHandler(MyReceiveHandler, win);
- RemoveTrackingHandler(MyTrackingHandler, win);
- }
-
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
- // MouseInContentRgn returns true if the current mouse is in the content
- // area of the window (but not necessarily in the visible rgn)
-
- Boolean MouseIsInContentRgn(DragReference theDrag, WindowPtr win)
- {
- Point mousePt;
-
- (void) GetDragMouse(theDrag, &mousePt, NULL);
- return PtInRgn(mousePt, ((WindowPeek) win)->contRgn);
- }
-
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
- // DragItemsAreAcceptable returns true if the contents (data) of
- // the drag are acceptable by a window of this application
- //
- // DragItemsAreAcceptable is called by the tracking and
- // receive handlers
-
- Boolean DragItemsAreAcceptable(DragReference theDrag)
- {
- OSErr err;
- unsigned short totalItems;
- ItemReference itemRef;
- Boolean acceptableFlag;
- HFSFlavor currHFSFlavor;
- Size flavorDataSize;
-
- acceptableFlag = false;
-
- // this app can only accept the drag of a single item
- err = CountDragItems(theDrag, &totalItems);
- if (err == noErr && totalItems == 1) {
-
- // get the reference number of the dragged item
- err = GetDragItemReferenceNumber(theDrag, 1, &itemRef);
-
- if (err == noErr) {
- flavorDataSize = sizeof(HFSFlavor);
- err = GetFlavorData(theDrag, itemRef, flavorTypeHFS, &currHFSFlavor,
- &flavorDataSize, 0);
-
- if (err == noErr)
- acceptableFlag = true;
- }
- }
- return acceptableFlag;
- }
-
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
- // DragIsNotInSourceWindow returns true if the drag in progress
- // is not in the same window it originated in
- //
- // DragIsNotInSourceWindow is called by the tracking and receive handlers
- //
- // Note that, if this application allowed items to be dragged within
- // its windows, this function would not be appropriate.
- // Instead, hilighting would probably occur in the source window
- // when the dragHasLeftSourceWindow flag is set, and the receive
- // handler wouldn't check this at all
-
- Boolean DragIsNotInSourceWindow(DragReference theDrag)
- {
- DragAttributes currDragFlags;
-
- (void) GetDragAttributes(theDrag, &currDragFlags);
- return ((currDragFlags & dragInsideSenderWindow) == 0);
- }
-
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
- // MyTrackingHandler is called by the drag manager whenever a drag is
- // over one of the application's windows
- //
- // upon entry, the current port has been set to win by the Drag Manager
-
- pascal OSErr MyTrackingHandler(DragTrackingMessage theMessage, WindowPtr win,
- void *handlerRefCon, DragReference theDrag)
- {
- #pragma unused (handlerRefCon)
-
- RgnHandle tempRgn;
- short mouseInWhichSpace;
- OSErr err;
-
- err = noErr;
-
- switch (theMessage) {
-
- case dragTrackingEnterHandler:
- //
- // Any initialization for this window handler.
- //
- gDragHandlerGlobals.acceptableDragFlag =
- DragItemsAreAcceptable(theDrag);
- gDragHandlerGlobals.hilitedSpace = -1;
-
- // let the drag manager know if we can't accept this drag
- if (!gDragHandlerGlobals.acceptableDragFlag)
- err = dragNotAcceptedErr;
- break;
-
- case dragTrackingEnterWindow:
- case dragTrackingInWindow:
- case dragTrackingLeaveWindow:
- //
- // Highlighting of the window during a drag is done
- // here. Do it only if we can accept these items
- // and we're not in the source window...
- //
- if (gDragHandlerGlobals.acceptableDragFlag
- && DragIsNotInSourceWindow(theDrag)) {
- //
- // Unless the mouse is leaving the visible area of the
- // window, check if it's in the window's content region
- //
- if (theMessage == dragTrackingLeaveWindow)
- mouseInWhichSpace = kNoSpace;
-
- else {
- Point localPt;
-
- (void) GetDragMouse(theDrag, &localPt, 0L);
- GlobalToLocal(&localPt);
- mouseInWhichSpace = WhichSpace(win, localPt);
- }
-
- //
- // If the mouse's space is not equal to the hilitedSpace
- // and the mouse is in a space (i.e., a new, different space.)
- //
- if ((mouseInWhichSpace != gDragHandlerGlobals.hilitedSpace)
- && (mouseInWhichSpace != kNoSpace)) {
- Rect nuSpaceRect, oldSpaceRect;
-
- if (gDragHandlerGlobals.hilitedSpace != kNoSpace) {
- //
- // There is a currently hilited space, unhilite it
- //
- GetSpaceRect(win, gDragHandlerGlobals.hilitedSpace, &oldSpaceRect);
- (void) HideDragHilite(theDrag);
- }
-
- GetSpaceRect(win, mouseInWhichSpace, &nuSpaceRect);
-
- // For cosmetic purposes
- InsetRect(&nuSpaceRect, 1, 1);
- tempRgn = NewRgn();
- RectRgn(tempRgn, &nuSpaceRect);
-
- // draw the hilight
- if (ShowDragHilite(theDrag, tempRgn, true) == noErr)
- // remember where hilighting is on
- gDragHandlerGlobals.hilitedSpace = mouseInWhichSpace;
-
- DisposeRgn(tempRgn);
- }
-
- //
- // else if the mouse is not in the content region
- // and the window is hilighted, erase the hilight
- //
- else if ((mouseInWhichSpace == kNoSpace)
- && (gDragHandlerGlobals.hilitedSpace != kNoSpace)) {
- Rect oldSpaceRect;
-
- GetSpaceRect(win, gDragHandlerGlobals.hilitedSpace, &oldSpaceRect);
-
- if (HideDragHilite(theDrag) == noErr)
- // remember that nothing is hilited
- gDragHandlerGlobals.hilitedSpace = kNoSpace;
- }
- }
- break;
-
- // do nothing for the leaveHandler message
- case dragTrackingLeaveHandler:
- break;
-
- // let the drag manager know if we didn't recognize the message
- default:
- err = paramErr;
- }
-
- return err;
- }
-
-
- //----------------------------------------------------------------------------
- // CreateAETarget
- //----------------------------------------------------------------------------
- #pragma segment AESupport
- OSErr CreateAETarget(ProcessSerialNumber *targetPSN, AEDesc *targetDesc)
- {
- OSErr err;
-
- err = AECreateDesc(typeProcessSerialNumber, (Ptr) targetPSN,
- sizeof(ProcessSerialNumber), targetDesc);
-
- return err;
- }
-
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
- // MyReceiveHandler is called by the drag manager whenever a drag is
- // ends on one of the application's windows
-
- pascal OSErr MyReceiveHandler(WindowPtr win, void *handlerRefCon,
- DragReference theDrag)
- {
- #pragma unused (handlerRefCon)
- ItemReference itemRef;
- Size dataSize;
- HFSFlavor theHFSFlavor;
- Boolean dataObtainedFlag;
- OSErr err;
-
- dataObtainedFlag = false;
- if (!DragItemsAreAcceptable(theDrag) ||
- !MouseIsInContentRgn(theDrag, win) ||
- !DragIsNotInSourceWindow(theDrag))
- return dragNotAcceptedErr;
-
- // There is only one item, so get its reference number.
- err = GetDragItemReferenceNumber(theDrag, 1, &itemRef);
- if (err != noErr)
- return err;
-
- if (!dataObtainedFlag) {
- dataSize = sizeof(HFSFlavor);
- err = GetFlavorData(theDrag, itemRef, flavorTypeHFS,
- &theHFSFlavor, &dataSize, 0);
- if (err == noErr)
- SendWindowSpaceSetter(win, theDrag, &theHFSFlavor.fileSpec);
- }
-
- InvalRect(&win->portRect);
-
- return err;
- }
-
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
- // OutlineRegion changes a region into a tracing of its border
- // which is appropriate for normal dragging
- //
- // OutlineRegion is called by DoWindowContentDrag
-
- void OutlineRegion(RgnHandle theRgn)
- {
- RgnHandle tempRgn;
-
- tempRgn = NewRgn();
- CopyRgn(theRgn, tempRgn);
- InsetRgn(tempRgn, 1, 1);
- DiffRgn(theRgn, tempRgn, theRgn);
- DisposeRgn(tempRgn);
- }
-
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
- // In our send data proc, we need to create a dummy file and call SetDrag-
- // ItemFlavorData with it to trick the Finder into believing that we did
- // what it asked. So now if the call to TrackDrag succeeds, we'll delete
- // this file and move the file via some Finder events.
- //
- pascal OSErr MySendDataProc(FlavorType flavorType, void *refCon,
- ItemReference theItem, DragReference theDrag)
- {
- Str63 fileName;
- long dirID;
- short vRefNum;
- OSErr result ;
- FSSpec locationSpec, dirSpec;
- Boolean isDir;
-
- if (flavorType == flavorTypeBlankSpec) {
- //
- // Attempt to create a unique file name
- //
- NumToString(TickCount() + theItem, fileName);
-
- result = GetDropFSSpec(theDrag, &dirSpec);
- if (result == noErr) {
- //
- // Get the directory ID and volume reference number from the drop location
- //
- vRefNum = dirSpec.vRefNum;
- result = DirIDFromFSSpec(&dirSpec, &dirID, &isDir);
-
- if (result == noErr) {
- result = FSMakeFSSpec(vRefNum, dirID, fileName, &locationSpec);
-
- if (result == fnfErr) {
- result = FSpCreate(&locationSpec, 'ttxt', 'TEXT', smSystemScript);
-
- if (result == noErr) {
- result = SetDragItemFlavorData(theDrag, theItem, flavorType,
- &locationSpec, sizeof(FSSpec), 0L);
- (void) FSpSetIsInvisible(&locationSpec);
- FailOSErr(result);
- }
- }
- else
- result = dupFNErr; /* force an error */
- }
- }
- }
- else
- DebugStr("\p it wants something other than blankSpec");
-
-
- if (result == noErr)
- return result;
- else {
- Debugger();
- return cantGetFlavorErr;
- }
- }
-
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
-
- OSErr AddPromiseHFSFlavor(DragReference drag, ItemReference item, FSSpecPtr spec)
- {
- PromiseHFSFlavor phfsObj;
- OSErr err;
- FInfo fileInfo;
-
- err = FSpGetFInfo(spec, &fileInfo);
- if (err == noErr) {
- phfsObj.fileType = fileInfo.fdType;
- phfsObj.fileCreator = fileInfo.fdCreator;
- phfsObj.fdFlags = fileInfo.fdFlags;
-
- }
-
- phfsObj.promisedFlavor = flavorTypeBlankSpec;
-
- if (err != noErr)
- return err;
-
- //
- // Goofy bug in the Drag Mgr. If you don't add the promiseHFS
- // flavor first, the drag will complete as expected, but the drop
- // will be put at the local coordinates of the initial drag.
- //
- err = AddDragItemFlavor(drag, item, flavorTypePromiseHFS,
- (Ptr) &phfsObj, sizeof(PromiseHFSFlavor), 0);
-
- err = AddDragItemFlavor(drag, item, flavorTypeBlankSpec,
- NULL, 0, 0);
-
- err = AddDragItemFlavor(drag, kRealSpecItemRef, flavorTypeRealSpec,
- (Ptr) spec, sizeof(FSSpec), 0);
-
- return err;
- }
-
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
- // GetDragDummyFile
- //
-
- OSErr GetDragDummyFile(DragReference theDrag, FSSpecPtr theSpec)
- {
- OSErr err;
- unsigned short totalItems;
- ItemReference itemRef;
- Boolean foundIt;
- Size flavorDataSize;
-
- foundIt = false;
-
- // this app can only accept the drag of a single item
- err = CountDragItems(theDrag, &totalItems);
-
- if ((err == noErr) && (foundIt == false)) {
- // get the reference number of the dragged item
- err = GetDragItemReferenceNumber(theDrag, 1, &itemRef);
-
- if (err == noErr) {
- // use GetFlavorFlags to check on flavor existence of PICT data
- // without forcing translation
-
- flavorDataSize = sizeof(FSSpec);
- err = GetFlavorData(theDrag, itemRef, flavorTypeBlankSpec, theSpec,
- &flavorDataSize, 0);
-
- if (err == noErr)
- foundIt = true;
- }
- }
-
- return err;
- }
-
-
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- // GetDragRegion
-
- OSErr GetDragRegion(WindowPtr win, RgnHandle dragRegion, short spaceNum)
- {
- Rect tempRect;
- OSErr err;
- Point offsetPt = {0,0};
- RgnHandle insetRegion = NewRgn();
- Handle iconSuiteToUse, spacesIconSuite;
-
- GetSpaceRect(win, spaceNum, &tempRect);
- InsetRect(&tempRect, 9, 9);
- GetSpaceIconSuite(win, spaceNum, &spacesIconSuite);
- SetEmptyRgn(insetRegion);
-
- if (spacesIconSuite != NULL)
- iconSuiteToUse = spacesIconSuite;
-
- err = IconSuiteToRgn(dragRegion, &tempRect, atNone, iconSuiteToUse);
-
- LocalToGlobal(&offsetPt);
- OffsetRgn(dragRegion, offsetPt.h, offsetPt.v);
- CopyRgn(dragRegion, insetRegion);
- InsetRgn(insetRegion, 1,1);
- DiffRgn(dragRegion, insetRegion, dragRegion);
-
- if ((iconSuiteToUse != spacesIconSuite) && (iconSuiteToUse != NULL))
- // Use this to get rid of the iconSuite if it's generic
- err = DisposeIconSuite(iconSuiteToUse, true);
-
- GISuiteFailed:
- return err;
- }
-
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
- // DoWindowContentDrag is called by the application whenever a drag
- // begins on one of the app's windows
-
- OSErr DoWindowContentDrag(WindowPtr win, EventRecord *theEvent)
- {
- OSErr err;
- DragReference theDrag;
- RgnHandle dragRgn;
- ItemReference theItem = 1;
- FSSpec windowSpec;
- short mouseUpModifiers;
- DragAttributes currDragFlags;
- GrafPtr oldPort;
- Point localPt;
- short dragSpace;
-
- // create a new drag
- err = NewDrag(&theDrag);
- if (err != noErr) goto Bail;
-
- GetPort(&oldPort);
- SetPort(win);
- localPt = theEvent->where;
- GlobalToLocal(&localPt);
- SetPort(oldPort);
- dragSpace = WhichSpace(win, localPt);
-
- if (dragSpace == kNoSpace) goto DisposeDragAndBail;
-
- err = GetSpaceSpec(win, dragSpace, &windowSpec);
- if (err != noErr) goto DisposeDragAndBail;
-
- err = AddPromiseHFSFlavor(theDrag, theItem, &windowSpec);
- if (err != noErr) goto DisposeDragAndBail;
-
- err = SetDragSendProc (theDrag, MySendDataProc, NULL);
- if (err != noErr) goto DisposeDragAndBail;
-
- dragRgn = NewRgn();
- err = GetDragRegion(win, dragRgn, dragSpace);
-
- // do the drag and clean up
- err = TrackDrag(theDrag, theEvent, dragRgn);
-
- DisposeRgn(dragRgn);
-
- if (err == noErr) {
- FSSpec dummyFile;
-
- //
- // the drag was successful, so delete the dummy file
- // we created and move the file with Apple events.
- //
- err = GetDragDummyFile(theDrag, &dummyFile);
-
- if (err == noErr) {
- err = FSpDelete(&dummyFile);
-
- if (err == noErr)
- err = HandleDragCloneMove(theDrag);
-
- FailOSErr(err);
- }
-
- // if the option key was not pressed at mouseUp and the drag ended
- // in the source application then this is a move operation and we
- // have to clear the source window
-
- (void) GetDragModifiers(theDrag, NULL, NULL, &mouseUpModifiers);
- (void) GetDragAttributes(theDrag, &currDragFlags);
-
- }
- else if (err != userCanceledErr)
- DebugStr("\pdrag failed");
-
- DisposeDragAndBail:
- DisposeDrag(theDrag);
-
- Bail:
- return err;
- }
-
-
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
-
- pascal OSErr DoAEOpenApplication(AppleEvent * theAppleEvent,
- AppleEvent * replyAppleEvent,
- long refCon)
- {
- #pragma unused (theAppleEvent, replyAppleEvent, refCon)
-
- // make an empty window
- (void) DoNewWindow();
- return noErr;
- }
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
-
- pascal OSErr DoAEOpenDocuments(AppleEvent * theAppleEvent,
- AppleEvent * replyAppleEvent,
- long refCon)
- {
- #pragma unused (replyAppleEvent, refCon)
- OSErr err;
- FSSpec currSpec;
- AEDescList docDescList;
- long itemCount, index;
- AEKeyword keyword;
- DescType typeCode;
- Size actualSize;
-
- // retrieve all documents from the Apple event and open them
- err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList,
- &docDescList);
- if (err != noErr) goto Bail;
-
- err = AECountItems(&docDescList, &itemCount);
- if (err != noErr) goto DisposeDocDescListAndBail;
-
- for (index = 1; index <= itemCount; index++) {
- err = AEGetNthPtr(&docDescList, index, typeFSS,
- &keyword, &typeCode, (Ptr) &currSpec, sizeof(FSSpec),
- &actualSize);
- if (err != noErr) goto DisposeDocDescListAndBail;
-
- }
-
- DisposeDocDescListAndBail:
- (void) AEDisposeDesc(&docDescList);
-
- Bail:
- if (err == noErr) return noErr;
- else return errAEEventNotHandled;
- }
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
-
- pascal OSErr DoAEQuitApplication(AppleEvent * theAppleEvent,
- AppleEvent * replyAppleEvent,
- long refCon)
- {
- #pragma unused (theAppleEvent, replyAppleEvent, refCon)
-
- DoQuit(); // set the quit flag (doesn't immediately quit)
- return noErr;
- }
-
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
- // DoHighLevelEvent
-
- void DoHighLevelEvent(EventRecord * theEventRecPtr)
- {
- (void) AEProcessAppleEvent(theEventRecPtr);
- }
-
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
- // InstallAppleEventHandlers
-
- OSErr InstallAppleEventHandlers()
- {
- OSErr err;
-
- err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
- (AEEventHandlerProcPtr) DoAEOpenApplication, 0, false);
-
- if (err == noErr)
- err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
- (AEEventHandlerProcPtr) DoAEOpenDocuments, 0, false);
-
- if (err == noErr)
- err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
- (AEEventHandlerProcPtr) DoAEQuitApplication, 0, false);
-
- if (err == noErr)
- err = AEInstallEventHandler(kPrivateEventClass, kAESetSpace,
- (AEEventHandlerProcPtr) DoAESetSpace, 0, false);
-
- return err;
- }
-
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
- // ConcatPascalStrings
-
- void ConcatPascalStrings(StringPtr s1, StringPtr s2)
- {
- short s1Length, s2Length;
-
- s1Length = s1[0];
- s2Length = s2[0];
- BlockMove(&s2[1], &s1[s1Length+1], s2Length);
- s1[0] = s1Length + s2Length;
- }
-
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
- // GetApplicationName uses the Process Manager to find
- // the current app's name
-
- OSErr GetApplicationName(StringPtr appNameString)
- {
- ProcessInfoRec appPIR;
- ProcessSerialNumber appPSN;
-
- appPSN.lowLongOfPSN = kCurrentProcess;
- appPSN.highLongOfPSN = 0;
-
- appPIR.processInfoLength = sizeof(ProcessInfoRec);
- appPIR.processAppSpec = NULL;
- appPIR.processName = appNameString;
-
- return GetProcessInformation(&appPSN, &appPIR);
- }
-
-
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
-
- void BuildSpecString(const FSSpec *spec,
- Str255 fullPathname)
- {
- OSErr result;
- CInfoPBRec pb;
- Str255 nodeName;
-
- fullPathname[0] = 0;
- result = noErr;
-
- /* Build a full pathname down to the volume */
- pb.dirInfo.ioNamePtr = nodeName;
- pb.dirInfo.ioVRefNum = spec->vRefNum;
- pb.dirInfo.ioDrParID = spec->parID;
- do {
- pb.dirInfo.ioFDirIndex = -1;
- pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
- result = PBGetCatInfoSync(&pb);
- concat(fullPathname, 3, nodeName, "\p:", fullPathname);
- } while ( (result == noErr) && (pb.dirInfo.ioDrDirID != fsRtDirID) );
-
- /* add the spec's name field and we're done */
- pstrcat(fullPathname, (StringPtr)spec->name);
- }
-
-
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
- // DrawWindow draws a window's picture in the window
-
- void DrawWindow(WindowPtr win)
- {
- Str255 str;
- FSSpec spec;
- WindowDataHandle winData;
- OSErr err;
-
- winData = (WindowDataHandle) GetWRefCon(win);
- if (winData != NULL) {
- Rect rct;
- short count;
- Handle iconSuite;
-
- for (count = 0; count < kNumberOfSpaces; count ++) {
- GetSpaceRect(win, count, &rct);
- FrameRect(&rct);
- err = GetSpaceSpec(win, count, &spec);
-
- if (err == noErr) {
- BuildSpecString(&spec, str);
- MoveTo(rct.right + 15, (rct.top + rct.bottom) / 2);
- DrawString(str);
- }
-
- GetSpaceIconSuite(win, count, &iconSuite);
-
- if (iconSuite != NULL) {
- InsetRect(&rct, 9, 9);
- err = PlotIconSuite(&rct, atNone, ttNone, iconSuite);
- }
- }
- }
- }
-
-
- // ReportStringInWindow draws a string in the specified window
- // if win is NULL, a new window is created and its WindowPtr is returned
-
- WindowPtr ReportStringInWindow(WindowPtr win, StringPtr theString)
- {
- DebugStr(theString);
- return win;
- }
-
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
- // CreateMenus makes menus the old-fashioned way
-
- void CreateMenus()
- {
- // create Apple menu
- gAppleMenuHandle = NewMenu(kAppleMenuID, "\p\024");
- AppendMenu(gAppleMenuHandle, "\pAbout FinderDrag...;(-");
- AddResMenu(gAppleMenuHandle, 'DRVR');
- InsertMenu(gAppleMenuHandle, 0);
-
- // create File menu
- gFileMenuHandle = NewMenu(kFileMenuID, "\pFile");
- AppendMenu(gFileMenuHandle, "\pNew/N;Open.../O;Close/W;(-;Quit/Q");
- InsertMenu(gFileMenuHandle, 0);
-
- DrawMenuBar();
- }
-
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
- // DoNewWindow creates a new window with an empty picture
- // and returns the window's WindowPtr
-
- WindowPtr DoNewWindow()
- {
- WindowPtr newWindow;
- Str63 windowNameStr;
- Str15 numStr;
- WindowDataHandle newWindowDataHandle;
- Rect windowRect;
-
- // one more window in the world
- gWindowCounter++;
-
- // find a size and place for the new window
- windowRect = qd.screenBits.bounds;
- SetRect(&windowRect, 60, 60, 360, 205);
- OffsetRect(&windowRect, 20 * (gWindowCounter % 10), 20 * (gWindowCounter % 10));
-
- // make a name for the window by concatenating gWindowCounter to the app name
- NumToString(gWindowCounter, numStr);
- if (GetApplicationName(windowNameStr) != noErr)
- *windowNameStr = 0;
- ConcatPascalStrings(windowNameStr, "\p ");
- ConcatPascalStrings(windowNameStr, numStr);
-
- // open the window
- if (gHasColorQuickdrawFlag)
- newWindow = NewCWindow(NULL, &windowRect, windowNameStr, true,
- documentProc, (WindowPtr) -1, true, 0);
- else
- newWindow = NewWindow(NULL, &windowRect, windowNameStr, true,
- documentProc, (WindowPtr) -1, true, 0);
-
- if (newWindow == NULL) goto Bail;
-
- SetPort(newWindow);
- ClipRect(&newWindow->portRect);
- TextSize(10);
-
- // attach my drag handlers to this window
-
- if (InstallDragHandlers(newWindow) != noErr)
- goto DisposeWindowAndBail;
-
- // allocate a data structure and a blank picture for the window
-
- newWindowDataHandle = (WindowDataHandle) NewHandle(sizeof(WindowData));
- if (newWindowDataHandle == NULL) goto RemoveHandlersAndBail;
-
- InitSpaces(newWindowDataHandle);
-
- SetWRefCon(newWindow, (long) newWindowDataHandle);
-
- return newWindow;
-
- RemoveHandlersAndBail:
- RemoveDragHandlers(newWindow);
-
- DisposeWindowAndBail:
- DisposeWindow(newWindow);
-
- Bail:
- gWindowCounter--;
- return NULL;
-
- }
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
- // DoCloseWindow disposes of a window and does all necessary clean-up
-
- void DoCloseWindow(WindowPtr win)
- {
- if (win != NULL) {
- DisposeHandle((Handle) GetWRefCon(win));
- RemoveDragHandlers(win);
- DisposeWindow(win);
- }
- }
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
- // DoQuit closes all open windows and sets the global quit flag
-
- void DoQuit()
- {
- while (FrontWindow() != NULL)
- DoCloseWindow(FrontWindow());
- gQuitFlag = true;
- }
-
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
- // DoAboutWindow
-
- void DoAboutWindow()
- {
- Alert(128, NULL);
- }
-
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
- // DoOpen
-
- void DoOpen()
- {
- StandardFileReply reply;
-
- StandardGetFile(NULL, -1, NULL, &reply);
- if (reply.sfGood) {
-
- // err = GetIconSuiteFromFinder(&reply.sfFile, &iconSuite);
- SetSpaceIndex(FrontWindow(), 1, &reply.sfFile);
-
- }
- else
- SysBeep(20);
-
- }
-
-
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
- // DoMenuCommand handles user menu selections
-
- void DoMenuCommand(long menuVal)
- {
- short theItem, theMenu;
- Str255 deskAccessoryName;
-
- theItem = LoWord(menuVal);
- theMenu = HiWord(menuVal);
-
- switch (theMenu) {
-
- case kAppleMenuID:
- if (theItem == kAboutMenuItem)
- DoAboutWindow();
-
- else {
- GetItem(gAppleMenuHandle, theItem, deskAccessoryName);
- (void) OpenDeskAcc(deskAccessoryName);
- }
- break;
-
- case kFileMenuID:
-
- if (theItem == kNewMenuItem)
- (void) DoNewWindow();
-
- else if (theItem == kOpenMenuItem)
- DoOpen();
-
- else if (theItem == kCloseMenuItem)
- DoCloseWindow(FrontWindow());
-
- else if (theItem == kQuitMenuItem)
- DoQuit();
-
- break;
-
- }
- HiliteMenu(0); // unhilight menu title
- }
-
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
-
- void main()
- {
- OSErr err;
- long gestResponse;
- Boolean canRunFlag;
-
-
- // initialize the toolbox
- InitGraf(&qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(NULL);
- InitCursor();
- FlushEvents(everyEvent,0);
- MaxApplZone();
-
- // can we run? let's be optimistic
- canRunFlag = true;
-
- // are the Apple Event and Drag managers available?
- // they simply must be
-
- err = Gestalt(gestaltAppleEventsAttr, &gestResponse);
- if (err != noErr ||
- (gestResponse & (1 << gestaltAppleEventsPresent)) == 0)
-
- canRunFlag = false;
-
- err = Gestalt(gestaltDragMgrAttr, &gestResponse);
- if (err != noErr ||
- (gestResponse & (1 << gestaltDragMgrPresent)) == 0)
-
- canRunFlag = false;
-
- if (!canRunFlag) ExitToShell(); // an alert would be nicer
-
-
- // use Gestalt to find out what the world is like
- // in particular, check for Color QuickDraw
-
- err = Gestalt(gestaltQuickdrawVersion, &gestResponse);
- if (err != noErr || gestResponse < 0x0100)
- gHasColorQuickdrawFlag = false;
- else
- gHasColorQuickdrawFlag = true;
-
-
- // now let's initialize everything and install the
- // drag and Apple event handlers
-
- // initialize application globals
-
- gQuitFlag = false;
- gWindowCounter = 0;
-
- // install Apple event handlers
- (void) InstallAppleEventHandlers();
- err = InitFinderAE();
- FailOSErr(err);
-
- // make the menus
- CreateMenus();
-
- // main event loop
-
- while (!gQuitFlag) {
-
- ProcessEvents();
-
- }
-
- // Good night
- }
-
-
- // —————————————————————————————————————————————————————————————————————————
- // —————————————————————————————————————————————————————————————————————————
-
- void ProcessEvents(void)
- {
- EventRecord mainEventRec;
- Boolean eventFlag;
-
- WindowPtr whichWindow;
- Rect tempRect;
-
- eventFlag = WaitNextEvent(everyEvent, &mainEventRec, 60*60*60, NULL);
-
- switch(mainEventRec.what) {
-
- case mouseDown:
- switch (FindWindow(mainEventRec.where, &whichWindow)) {
-
- case inSysWindow: // desk accessory window
- SystemClick(&mainEventRec, whichWindow);
- break;
-
- case inMenuBar:
- DoMenuCommand(MenuSelect(mainEventRec.where));
- break;
-
- case inDrag:
- tempRect = qd.screenBits.bounds;
- DragWindow(whichWindow, mainEventRec.where, &tempRect);
- break;
-
- case inGoAway:
- if (TrackGoAway(whichWindow, mainEventRec.where))
- DoCloseWindow(whichWindow);
- break;
-
- case inContent:
-
- // check to see if the user is starting a drag
- if (WaitMouseMoved(mainEventRec.where))
-
- // if so, do the drag magic
- DoWindowContentDrag(whichWindow, &mainEventRec);
-
- else if (whichWindow != FrontWindow())
- SelectWindow(whichWindow);
- break;
- }
- break;
-
- case updateEvt:
-
- whichWindow = (WindowPtr) mainEventRec.message;
-
- if ( ((WindowPeek)whichWindow)->windowKind != dialogKind )
- {
- SetPort(whichWindow);
- BeginUpdate(whichWindow);
-
- EraseRect(&whichWindow->portRect);
- DrawWindow(whichWindow);
-
- EndUpdate(whichWindow);
- }
- break;
-
- case keyDown:
- case autoKey:
- if (mainEventRec.modifiers & cmdKey)
- DoMenuCommand(MenuKey(mainEventRec.message & charCodeMask));
- break;
-
- case kHighLevelEvent:
- DoHighLevelEvent(&mainEventRec);
- break;
-
- // a real app should handle all of these events.
- // Since the code is in Inside Mac:Mac Toolbox Essentials,
- // you really have no excuse for not supporting all the
- // standard low-level events
-
-
-
- // however, this is just a sample program, so I have an excuse
-
- case activateEvt:
- case osEvt:
- case diskEvt:
- case mouseUp:
- break;
- }
- }
-
-